<template>
  <div class="v-upload">
    <div
      class="upload flex-center"
      @click="clicks"
      @mouseenter="hanlderHover(true, $event)"
      @mouseleave="hanlderHover(false, $event)"
    >
      <input
        ref="inp"
        type="file"
        name=""
        id=""
        :accept="accept"
        @change="handlerChange"
      />
      <i class="upload-icon" v-if="!imgUrl || hovering"></i>
      <img v-else :src="imgUrl" alt="" />
    </div>
    <i v-if="imgUrl" class="close-icon" @click="clear"></i>
  </div>
</template>
<script>
import ajax from "./ajax";
export default {
  props: {
    type: {
      type: String,
      default: "avatar",
    },
    action: {
      type: String,
      required: true,
    },
    name: {
      type: String,
      default: "file",
    },
    data: Object,
    headers: Object,
    withCredentials: Boolean,
    httpRequest: {
      type: Function,
      default: ajax,
    },
    accept: String,
    beforeUpload: Function,
    onProgress: Function,
    onSuccess: Function,
    onError: Function,
  },
  data() {
    return {
      reqs: {},
      imgUrl: "",
      hovering: false,
    };
  },
  mounted() {},
  methods: {
    clicks() {
      this.$refs.inp.click();
    },
    handlerChange(ev) {
      const files = ev.target.files;
      if (!files) return;
      this.uploadFiles(files);
    },
    uploadFiles(files) {
      let postFiles = Array.prototype.slice.call(files);
      postFiles = postFiles.slice(0, 1);
      if (postFiles.length === 0) {
        return;
      }
      postFiles.forEach((rawFile) => {
        this.upload(rawFile);
      });
    },
    upload(rawFile) {
      this.$refs.inp.value = null;
      if (!this.beforeUpload) {
        return this.post(rawFile);
      }
      const before = this.beforeUpload(rawFile);
      if (before && before.then) {
        before.then(
          (processedFile) => {
            const fileType = Object.prototype.toString.call(processedFile);
            if (fileType === "[object File]" || fileType === "[object Blob]") {
              if (fileType === "[object Blob]") {
                processedFile = new File([processedFile], rawFile.name, {
                  type: rawFile.type,
                });
              }
              for (const p in rawFile) {
                if (Object.prototype.hasOwnProperty.call(rawFile, p)) {
                  processedFile[p] = rawFile[p];
                }
              }
              this.post(processedFile);
            } else {
              this.post(rawFile);
            }
          },
          () => {
            //
          }
        );
      } else if (before !== false) {
        this.post(rawFile);
      } else {
        //
      }
    },
    post(rawFile) {
      if (process.env.NODE_ENV == "development") {
        this.imgUrl = URL.createObjectURL(rawFile);
      }
      const { uid } = rawFile;
      const options = {
        headers: this.headers,
        withCredentials: this.withCredentials,
        file: rawFile,
        data: this.data,
        filename: this.name,
        action: this.action,
        onProgress: (e) => {
          this.onProgress && this.onProgress(e, rawFile);
        },
        onSuccess: (res) => {
          this.onSuccess && this.onSuccess(res, rawFile);
          this.imgUrl = URL.createObjectURL(rawFile);
          delete this.reqs[uid];
        },
        onError: (err) => {
          this.onError && this.onError(err, rawFile);
          delete this.reqs[uid];
        },
      };
      const req = this.httpRequest(options);
      this.reqs[uid] = req;
      if (req && req.then) {
        req.then(options.onSuccess, options.onError);
      }
    },
    hanlderHover(bol) {
      this.hovering = bol;
    },
    clear() {
      this.imgUrl = "";
    },
  },
};
</script>
<style lang="less" scoped>
.v-upload {
  position: relative;
  width: 60px;
  height: 60px;
  line-height: 30px;
  text-align: center;
  border-radius: 50%;
  border: 1px solid @border-color;
  cursor: pointer;
  .upload {
    height: 100%;
  }
  input {
    display: none;
  }
  .upload-icon {
    width: 50%;
    height: 50%;
    background: url("./upload.svg") no-repeat;
    background-size: 100% 100%;
  }
  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
  }
  .close-icon {
    position: absolute;
    top: -15px;
    right: -15px;
    width: 15px;
    height: 15px;
    transition: 0.3s;
    &::before,
    &::after {
      content: "";
      width: 100%;
      height: 1px;
      position: absolute;
      top: 50%;
      left: 50%;
      background-color: #aaa;
      transform: translate(-50%, -50%) rotate(45deg);
    }
    &::after {
      transform: translate(-50%, -50%) rotate(-45deg);
    }
    &:hover {
      transform: rotate(180deg);
    }
  }
}
</style>
